package syscommand

import (
	"encoding/json"
	"errors"
	"strings"
    
    "collecter/app/common/enum"
    "collecter/app/common/helper"
)

type MakeModel struct {
	MdlName string
	Table   string
	BaseCmd
}

type ColumnType struct {
	ColumnName string `json:"column_name,omitempty"`
	DataType   string `json:"data_type,omitempty"`
}

func NewMakeModel() *MakeModel {
	return &MakeModel{}
}

func (mc *MakeModel) Configure() {
	// fmt.Println("MakeCtl -> Configure")
	mc.StringVar(&mc.MdlName, "name", "", "模型名称，可以指定包名")
	mc.StringVar(&mc.Table, "table", "", "model 对应的数据表名")
}

func (mc *MakeModel) Execute() error {
	// code ...
	// fmt.Printf("%+v\n", mc)
	if len(mc.MdlName) == 0 {
		return errors.New("控制器名称不能为空")
	}

	path, pkg, model, parseErr := mc.ParsePathAndPkg(mc.MdlName, "model")
	if parseErr != nil {
		return parseErr
	}

	filename := path + helper.CamelString(model, false) + ".go"
	// fmt.Println(filename)

	var mdlTplStr string
	tplFile := enum.ROOT_DIR + "console/tpl/model.tpl"
	// fmt.Println("tplFile ========== ", tplFile)

	if err, val := helper.ReadFileContent(tplFile, false); err != nil {
		return err
	} else {
		mdlTplStr = val
	}
	// fmt.Println("======= before ======== ", ctlTplStr)

	fieldInfos := make([]ColumnType, 0, 0)
	if d, err := mc.getFields(); err != nil {
		return err
	} else {
		fieldInfos = d
	}

	fieldStr := ""
	for _, field := range fieldInfos {
		cField := helper.CamelString(field.ColumnName, false)
		sField := helper.SnakeString(field.ColumnName)
		fieldStr += cField + " " + field.DataType + " `json:\"" + sField + ",omitempty\"`\n    "
	}
	// fmt.Printf("======787878====== %+v\n", fieldInfos)
	// fmt.Println(fieldStr)

	mdlTplStr = strings.ReplaceAll(mdlTplStr, "{{pkg}}", pkg)
	mdlTplStr = strings.ReplaceAll(mdlTplStr, "{{mdlName}}", model)
	mdlTplStr = strings.ReplaceAll(mdlTplStr, "{{tableFields}}", fieldStr)
	// fmt.Println("========= after ========== ", ctlTplStr)

	if err := helper.WriteToFile(filename, mdlTplStr); err != nil {
		return err
	}

	return nil
}

/*
 *  getFields
 * @Description: 获取表格所有字段的字段名和字段类型
 * @receiver mc
 * @return []ColumnType
 * @return error
 */
func (mc *MakeModel) getFields() ([]ColumnType, error) {
	var rst []ColumnType
	var tableInfo []map[string]interface{}
	database := helper.Configer.GetString("mysql.dbname")
	sql := "select `column_name`,`data_type` from `information_schema`.`COLUMNS` where `TABLE_NAME` = '" + mc.Table + "' " +
		"and `TABLE_SCHEMA` = '" + database + "' order by ORDINAL_POSITION asc"

	if err := helper.Db.Raw(sql).Scan(&tableInfo).Error; err != nil {
		return rst, err
	}
	tableInfoJson, _ := json.Marshal(tableInfo)

	_ = json.Unmarshal(tableInfoJson, &rst)
	// fmt.Printf("=========res======= %+v\n", rst[0].ColumnName)

	for idx, val := range rst {
		dataType := val.DataType
		switch dataType {
		case "tinyint":
			dataType = "int8"
		case "smallint":
			dataType = "int16"
		case "mediumint":
			dataType = "int32"
		case "int":
			dataType = "int"
		case "bigint":
			dataType = "int64"
		case "float":
			dataType = "float32"
		case "double":
			dataType = "float64"
		case "decimal":
			dataType = "float64"
		case "date", "time", "year", "datetime", "timestamp", "char", "varchar", "tinyblob", "tinytext", "blob",
			"text", "mediumblob", "mediumtext", "longblob", "longtext":
			dataType = "string"
		}
		rst[idx].DataType = dataType
	}
	// fmt.Printf("========= %+v\n", rst)
	return rst, nil
}
